package com.ruicar.afs.cloud.manage.common.service.impl;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruicar.afs.cloud.basic.api.fegin.repayment.RepaymentPlanFegin;
import com.ruicar.afs.cloud.bizcommon.cms.dto.CmsResponse;
import com.ruicar.afs.cloud.bizcommon.cms.enums.CodeResponseEnum;
import com.ruicar.afs.cloud.bizcommon.cms.enums.SuccessResponseEnum;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.translog.service.GlobalTransService;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.enums.ServiceNameEnum;
import com.ruicar.afs.cloud.common.enums.ToBasicSyncDataUrl;
import com.ruicar.afs.cloud.common.modules.contract.enums.CaseStatusEnum;
import com.ruicar.afs.cloud.common.modules.contract.enums.ContractBusinessEnum;
import com.ruicar.afs.cloud.common.modules.contract.enums.DataSourceEnum;
import com.ruicar.afs.cloud.common.modules.contract.enums.ProcessStatusEnum;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import com.ruicar.afs.cloud.common.vo.ChangePlanSyncDataRequestVo;
import com.ruicar.afs.cloud.manage.cms.service.IcosToCmsChangeRepaymentService;
import com.ruicar.afs.cloud.manage.common.entity.ManageApplyRecord;
import com.ruicar.afs.cloud.manage.common.entity.ManageRepaymentDateChange;
import com.ruicar.afs.cloud.manage.common.entity.ManageVerifyCode;
import com.ruicar.afs.cloud.manage.common.mapper.ManageRepaymentDateChangeMapper;
import com.ruicar.afs.cloud.manage.common.service.ManageApplyRecordService;
import com.ruicar.afs.cloud.manage.common.service.ManageRepaymentDateChangeService;
import com.ruicar.afs.cloud.manage.common.service.ManageVerifyCodeService;
import com.ruicar.afs.cloud.manage.common.util.CreatCaseNoUtil;
import com.ruicar.afs.cloud.manage.mq.sender.ManageSender;
import com.ruicar.afs.cloud.manage.workflow.processor.ContractWorkFlowSaveApproveInfoProcessor;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.List;

/**
 * @author: Lee
 * @date 2020-05-30 04:45:15
 * @description
 */
@Service
@AllArgsConstructor
public class ManageRepaymentDateChangeServiceImpl extends ServiceImpl<ManageRepaymentDateChangeMapper, ManageRepaymentDateChange> implements ManageRepaymentDateChangeService {

    private final ManageApplyRecordService manageApplyRecordService;
    private final RepaymentPlanFegin repaymentPlanFegin;
    private final ManageSender manageSender;
    private final ManageVerifyCodeService manageVerifyCodeService;
    private final ContractWorkFlowSaveApproveInfoProcessor saveApproveInfoProcessor;
    private final GlobalTransService globalTransService;
    private final IcosToCmsChangeRepaymentService icosToCmsChangeRepaymentService;

    @Override
    public void submitChange(ManageRepaymentDateChange change) {
        //二次计算校验计算结果是否正确   未偿本金*实际利率/36500*逾期天数
        long betweenDay = DateUtil.between(change.getOldDueDate(), change.getNewDueDate(), DateUnit.DAY, false);
        if (betweenDay > 0) {
            BigDecimal isLeapYear = new BigDecimal(36500);
            if(DateUtil.isLeapYear(DateUtil.year(DateUtil.date()))){
                isLeapYear = new BigDecimal(36600);
            }
            BigDecimal calculate = change.getRemainPrinciple().multiply(change.getRealInterestRate())
                    .divide(isLeapYear, 4).multiply(new BigDecimal(betweenDay))
                    .setScale(2, BigDecimal.ROUND_HALF_UP);
            //四舍五入，误差控制在0.1以内
            if (calculate.subtract(change.getExtraInterest()).abs().compareTo(new BigDecimal(0.1)) == 1) {
                throw new AfsBaseException("额外利息计算有误，请重新选择日期进行计算");
            }
        }

        List<ManageVerifyCode> list = manageVerifyCodeService.list(Wrappers.<ManageVerifyCode>query().lambda()
                .eq(ManageVerifyCode::getPhone, change.getPhone())
                .orderByDesc(ManageVerifyCode::getCreateTime)
        );
        if (list.size() != 0) {
            if (list.get(0).getVerifyCode().equals(change.getVerifyCode())) {

            } else {
                throw new AfsBaseException("验证码校验失败");
            }
        }

        if (EmptyUtils.isEmpty(change.getId())) {
            change.setCaseNo(CreatCaseNoUtil.GeneratorCaseNo(ContractBusinessEnum.repaymentDateChange));
            change.setProcessStatus(ProcessStatusEnum.approved);
            change.setApplyDate(DateUtil.date());
            change.setEndDate(DateUtil.date());
            this.save(change);
            this.updateById(change);
            //保存变更操作记录表数据
            ManageApplyRecord record = new ManageApplyRecord();
            record.setContractNo(change.getContractNo());
            record.setCaseNo(change.getCaseNo());
            record.setContractBusiness(ContractBusinessEnum.repaymentDateChange);
            record.setCaseStatus(CaseStatusEnum.APPROVED);
            record.setDataSource(change.getDataSource());
            record.setBusinessSource(change.getBusinessSource());
            record.setApplyTime(DateUtil.date());
            record.setEndDate(change.getEndDate());
            manageApplyRecordService.save(record);
            saveApproveInfoProcessor.saveApproveRecord(record, ContractBusinessEnum.repaymentDateChange);
            //向basic同步结果
            if (DataSourceEnum.icos == change.getDataSource()) {
                ChangePlanSyncDataRequestVo vo = new ChangePlanSyncDataRequestVo();
                vo.setContractNo(change.getContractNo());
                vo.setCostAmt(change.getPoundage());
                vo.setDueDate(change.getNewDueDate());
                vo.setExtraInterest(change.getExtraInterest());
                IResponse<Boolean> response = globalTransService.post(String.valueOf(change.getId()), AfsEnumUtil.key(ServiceNameEnum.BASIC), AfsEnumUtil.key(ToBasicSyncDataUrl.SYNC_CHANGE_REPAYMENT_DATA), vo, new TypeReference<Boolean>() {
                });
                if (CommonConstants.FAIL.equals(response.getCode())) {
                    throw new AfsBaseException("还款日变更结果数据推送至basic服务失败，请重试！");
                }
            } else {
                CmsResponse response = icosToCmsChangeRepaymentService.syncToCmsChangeRepaymentResult(change);
                if (AfsEnumUtil.key(SuccessResponseEnum.FAIL).equals(response.getSuccess()) && !AfsEnumUtil.key(CodeResponseEnum.M10051).equals(response.getCode())) {
                    throw new AfsBaseException("还款日变更结果数据推送至cms系统失败，请重试！");
                }
            }
            repaymentPlanFegin.updateRepaymentPlan(change.getContractNo(), change.getNewDueDate(), change.getPoundage());
        } else {
            this.updateById(change);
        }

    }

    /**
     * 定时发送还款日变更数据
     */
    @Override
    public void sendDuedatechange() {

        List<ManageRepaymentDateChange> manageRepaymentDateChanges = this.list(Wrappers.<ManageRepaymentDateChange>query().lambda()
                .lt(ManageRepaymentDateChange::getEndDate, DateUtil.today())//案件审批完成时间小于当前时间
        );
        for (ManageRepaymentDateChange manageRepaymentDateChange : manageRepaymentDateChanges) {
            try {
                JSONObject json = new JSONObject();
                json.put("CamainId", manageRepaymentDateChange.getApplyNo());//申请单号
                json.put("ContractNo", manageRepaymentDateChange.getContractNo());//合同号
                json.put("ChangeDate", manageRepaymentDateChange.getNewDueDate());//新的还款日
                manageSender.sendDuedatechange(json.toJSONString());
            } catch (Exception e) {
                log.error("发送CMS合同提前还款数据数据异常[{0}],异常信息:[{1}]", e);
            }
        }

    }
}
